/*******************************************************************************
 * Copyright 2011-2012 Dik Grapendaal
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package sh.grapendaal.tsuushin.service.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.stereotype.Service;

import sh.grapendaal.tsuushin.permission.PermissionData;
import sh.grapendaal.tsuushin.permission.PermissionString;
import sh.grapendaal.tsuushin.service.PermissionService;
import sh.grapendaal.tsuushin.tracking.User;

@Service
public class PermissionServiceImpl implements PermissionService {
	private Set<PermissionString> permissions = new HashSet<PermissionString>();
	private Map<User, PermissionData> users = new Hashtable<User, PermissionData>();

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean registerPermission(String permission) {
		return permissions.add(new PermissionString(permission));
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean unregisterPermission(String permission) {
		return permissions.remove(new PermissionString(permission));
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean permissionExists(String permission) {
		return permissions.contains(new PermissionString(permission));
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public List<String> getUsablePermissions() {
		List<String> list = new ArrayList<String>();
		for (PermissionString permission : permissions) {
			list.add(permission.toString());
		}
		return list;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void addUser(User user) {
		this.addUser(user, null);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void addUser(User user, String hashedPassword) {
		users.put(user, new PermissionData(user, hashedPassword));
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void removeUser(User user) {
		users.remove(user);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean isUserKnown(User user) {
		return users.containsKey(user);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean grantPermission(User user, String permission) {
		if (!this.isUserKnown(user)) {
			throw new IllegalArgumentException("User " + user + " not known in Permission Service.");
		}
		if (!this.permissionExists(permission)) {
			throw new IllegalArgumentException("Permission \"" + permission
					+ "\" not registered in Permission Service.");
		}

		return users.get(user).grantPermission(new PermissionString(permission));
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean revokePermission(User user, String permission) {
		if (!this.isUserKnown(user)) {
			throw new IllegalArgumentException("User " + user + " not known in Permission Service.");
		}
		if (!this.permissionExists(permission)) {
			throw new IllegalArgumentException("Permission \"" + permission
					+ "\" not registered in Permission Service.");
		}

		return users.get(user).revokePermission(new PermissionString(permission));
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean hasPermission(User user, String permission) {
		if (!this.isUserKnown(user)) {
			throw new IllegalArgumentException("User " + user + " not known in Permission Service.");
		}
		if (!this.permissionExists(permission)) {
			throw new IllegalArgumentException("Permission \"" + permission
					+ "\" not registered in Permission Service.");
		}

		return users.get(user).hasPermission(new PermissionString(permission));
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean isBotOwner(User user) {
		return this.hasPermission(user, PermissionService.PERMISSION_BOT_OWNER);
	}
}
